/* Copyright (c) [2025] [zhi1208@126.com]
 * SPDX-License-Identifier: MIT
 */

/*********************
 *      INCLUDES
 *********************/
#include "lvgl.h"
#include "hmi_conf.h"
#include "hmi_subject.h"
#include "hmi_theme.h"
#include "hmi_asset.h"
#include "hmi_pg_navigation.h"
#include "hmi_pages.h"

/*********************
 *      DEFINES
 *********************/

/**********************
 *      TYPEDEFS
 **********************/
typedef enum
{
    BTN_THEME,
    BTN_TRANSLATION,
    BTN_ROTATE,
    BTN_TWO,
    BTN_NUM
} ctrl_btn_enum_t;

typedef struct
{
    lv_obj_t *obj;
    lv_obj_t *parent;
    lv_obj_t *icon;
    lv_subject_t *subject;
} ctrl_btn_t;

/**********************
 *  STATIC PROTOTYPES
 **********************/
static void ctrl_center_up_anim_cplt_cb(lv_anim_t *a);
static void ctrl_center_down_anim_cplt_cb(lv_anim_t *a);

static void theme_subj_observer_cb(lv_observer_t *observer, lv_subject_t *subject);
static void translations_subj_observer_cb(lv_observer_t *observer, lv_subject_t *subject);
static void rotate_subj_observer_cb(lv_observer_t *observer, lv_subject_t *subject);

static void ctrl_center_rebuild();
static void style_init();
static void style_deinit();
static void grid_init();
static void top_bar_init();
static void top_bar_deinit();
static void ctrl_btn_init();
static void slider_init();

static void setting_icon_clicked_cb(lv_event_t *e);
static void translation_btn_clicked_cb(lv_event_t *e);

static void ctrl_center_gesture_cb();

/**********************
 *  STATIC VARIABLES
 **********************/
static lv_obj_t *ctrl_center;
static bool ctrl_center_is_down;

static lv_obj_t *top_bar_wrap;
static lv_obj_t *bl_slider_wrap;
static lv_obj_t *vol_slider_wrap;

static lv_style_t slider_styl;
static lv_style_t slider_knob_styl;
static lv_style_t slider_indicator_style;
static lv_style_t btn_styl;
static lv_style_t btn_checked_styl;

static ctrl_btn_t ctrl_btn_list[BTN_NUM];

static lv_obj_t *setting_icon;

static lv_font_t *top_bar_title_font;

/**********************
 *      MACROS
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
 **********************/
void hmi_ctrl_center_init()
{
    ctrl_center = lv_obj_create(lv_layer_top());
    lv_obj_move_foreground(ctrl_center);
    lv_obj_remove_style_all(ctrl_center);
    lv_obj_set_size(ctrl_center, lv_pct(100), lv_pct(100));
    lv_obj_set_pos(ctrl_center, 0, -lv_pct(100));
    lv_obj_set_style_bg_color(ctrl_center, lv_color_black(), 0);
    lv_obj_set_style_bg_opa(ctrl_center, LV_OPA_70, 0);
    lv_obj_set_style_text_color(ctrl_center, lv_color_white(), 0);
    lv_obj_set_style_pad_row(ctrl_center, 10, 0);
    lv_obj_set_style_pad_column(ctrl_center, 10, 0);
    lv_obj_set_grid_align(ctrl_center, LV_GRID_ALIGN_SPACE_EVENLY, LV_GRID_ALIGN_SPACE_EVENLY);

    style_init();
    grid_init();
    top_bar_init();
    ctrl_btn_init();
    slider_init();

    lv_subject_add_observer_obj(&hmi_theme_subj, theme_subj_observer_cb, ctrl_btn_list[BTN_THEME].obj, NULL);
    lv_subject_add_observer_obj(&hmi_translations_subj, translations_subj_observer_cb, ctrl_btn_list[BTN_TRANSLATION].obj, NULL);
    lv_subject_add_observer_obj(&hmi_rotate_subj, rotate_subj_observer_cb, ctrl_btn_list[BTN_ROTATE].obj, NULL);

    hmi_add_push_start_cb(ctrl_center_gesture_cb);
    hmi_add_rebuild_all_pg_cplt_cb(ctrl_center_rebuild);
}

lv_obj_t *hmi_get_ctrl_center_obj()
{
    return ctrl_center;
}

void hmi_ctrl_center_up()
{
    lv_obj_update_layout(ctrl_center);
    int32_t start_val = lv_obj_get_y(ctrl_center);
    int32_t height = lv_obj_get_height(ctrl_center);

    lv_anim_t a;
    lv_anim_init(&a);
    lv_anim_set_var(&a, ctrl_center);
    lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_y);
    lv_anim_set_values(&a, start_val, -height);
    lv_anim_set_path_cb(&a, lv_anim_path_ease_out);
    lv_anim_set_duration(&a, 300 * hmi_g_anim_rate);
    lv_anim_set_completed_cb(&a, ctrl_center_up_anim_cplt_cb);
    lv_anim_start(&a);
}

void hmi_ctrl_center_down()
{
    lv_obj_update_layout(ctrl_center);
    int32_t start_val = lv_obj_get_y(ctrl_center);
    int32_t height = lv_obj_get_height(ctrl_center);

    lv_anim_t a;
    lv_anim_init(&a);
    lv_anim_set_var(&a, ctrl_center);
    lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_y);
    lv_anim_set_values(&a, start_val, 0);
    lv_anim_set_path_cb(&a, lv_anim_path_ease_out);
    lv_anim_set_duration(&a, 300 * hmi_g_anim_rate);
    lv_anim_set_completed_cb(&a, ctrl_center_down_anim_cplt_cb);
    lv_anim_start(&a);
}

/**********************
 *   STATIC FUNCTIONS
 **********************/
static void ctrl_center_rebuild()
{
    ctrl_center_up_anim_cplt_cb(NULL);

    style_deinit();
    top_bar_deinit();
    lv_obj_del(ctrl_center);

    hmi_ctrl_center_init();
}

static void ctrl_center_up_anim_cplt_cb(lv_anim_t *a)
{
    LV_UNUSED(a);

    ctrl_center_is_down = 0;

    hmi_set_swipe_left_right_cb(hmi_pg_pop);
    hmi_set_swipe_up_cb(hmi_back_home);
}

static void ctrl_center_down_anim_cplt_cb(lv_anim_t *a)
{
    LV_UNUSED(a);

    ctrl_center_is_down = 1;

    hmi_set_swipe_left_right_cb(hmi_ctrl_center_up);
    hmi_set_swipe_up_cb(hmi_ctrl_center_up);
}

static void theme_subj_observer_cb(lv_observer_t *observer, lv_subject_t *subject)
{
    LV_UNUSED(observer);

    int32_t theme = lv_subject_get_int(subject);

    switch (theme)
    {
    case HMI_THEME_LIGHT:
        lv_image_set_src(ctrl_btn_list[BTN_THEME].icon, hmi_png("moon_slash_circle"));
        break;

    case HMI_THEME_DARK:
        lv_image_set_src(ctrl_btn_list[BTN_THEME].icon, hmi_png("moon_circle_fill"));
        break;

    default:
        break;
    }

    lv_style_set_bg_color(&slider_indicator_style, hmi_color_master);
    lv_style_set_bg_color(&btn_checked_styl, hmi_color_master);
    lv_obj_fade_in(ctrl_btn_list[BTN_THEME].icon, 500 * hmi_g_anim_rate, 0);
    lv_obj_report_style_change(NULL);
}

static void translations_subj_observer_cb(lv_observer_t *observer, lv_subject_t *subject)
{
    LV_UNUSED(observer);

    int32_t lang = lv_subject_get_int(subject);

    switch (lang)
    {
    case HMI_TRANS_ZH:
        lv_image_set_src(ctrl_btn_list[BTN_TRANSLATION].icon, hmi_png("translate_c2e"));
        break;

    case HMI_TRANS_EN:
        lv_image_set_src(ctrl_btn_list[BTN_TRANSLATION].icon, hmi_png("translate_e2c"));
        break;

    default:
        break;
    }

    lv_obj_fade_in(ctrl_btn_list[BTN_TRANSLATION].icon, 500 * hmi_g_anim_rate, 0);
    lv_obj_report_style_change(NULL);
}

static void rotate_subj_observer_cb(lv_observer_t *observer, lv_subject_t *subject)
{
    LV_UNUSED(observer);

    int32_t rotation = lv_subject_get_int(subject);

    switch (rotation)
    {
    case HMI_ROTAE_DEF:
        lv_image_set_src(ctrl_btn_list[BTN_ROTATE].icon, hmi_png("rectangle_rotate"));
        break;

    case HMI_ROTAE_90:
        lv_image_set_src(ctrl_btn_list[BTN_ROTATE].icon, hmi_png("rectangle_portrait_rotate"));
        break;

    default:
        break;
    }

    lv_obj_fade_in(ctrl_btn_list[BTN_ROTATE].icon, 500 * hmi_g_anim_rate, 0);
    lv_obj_report_style_change(NULL);
}

static void style_init()
{
    lv_style_init(&slider_styl);
    lv_style_set_size(&slider_styl, lv_pct(95), lv_pct(95));
    lv_style_set_radius(&slider_styl, LV_RADIUS_CIRCLE);
    lv_style_set_bg_color(&slider_styl, lv_color_white());

    lv_style_init(&slider_knob_styl);
    lv_style_set_bg_opa(&slider_knob_styl, LV_OPA_TRANSP);

    lv_style_init(&slider_indicator_style);
    lv_style_set_radius(&slider_indicator_style, 0);

    lv_style_init(&btn_checked_styl);

    lv_style_init(&btn_styl);
    lv_style_set_size(&btn_styl, lv_pct(85), lv_pct(85));
    lv_style_set_radius(&btn_styl, LV_RADIUS_CIRCLE);
    lv_style_set_shadow_width(&btn_styl, 0);
    lv_style_set_bg_color(&btn_styl, lv_color_white());
    lv_style_set_bg_opa(&btn_styl, LV_OPA_30);
}

static void style_deinit()
{
    lv_style_reset(&slider_styl);
    lv_style_reset(&slider_knob_styl);
    lv_style_reset(&slider_indicator_style);
    lv_style_reset(&btn_checked_styl);
    lv_style_reset(&btn_styl);
}

static void grid_init()
{
    top_bar_wrap = lv_obj_create(ctrl_center);
    lv_obj_remove_style_all(top_bar_wrap);

    bl_slider_wrap = lv_obj_create(ctrl_center);
    lv_obj_remove_style_all(bl_slider_wrap);

    vol_slider_wrap = lv_obj_create(ctrl_center);
    lv_obj_remove_style_all(vol_slider_wrap);

    for (size_t i = 0; i < BTN_NUM; ++i)
    {
        ctrl_btn_list[i].parent = lv_obj_create(ctrl_center);
        lv_obj_remove_style_all(ctrl_btn_list[i].parent);
    }

    int32_t hor_res = lv_display_get_horizontal_resolution(lv_display_get_default());
    int32_t ver_res = lv_display_get_vertical_resolution(lv_display_get_default());

    if (hor_res >= ver_res)
    {
        static int32_t column_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
        static int32_t row_dsc[] = {LV_GRID_FR(3), LV_GRID_FR(2), LV_GRID_FR(2), LV_GRID_FR(2), LV_GRID_FR(2), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
        lv_obj_set_grid_dsc_array(ctrl_center, column_dsc, row_dsc);

        lv_obj_set_grid_cell(top_bar_wrap, LV_GRID_ALIGN_STRETCH, 0, 8, LV_GRID_ALIGN_STRETCH, 0, 1);
        lv_obj_set_grid_cell(bl_slider_wrap, LV_GRID_ALIGN_STRETCH, 6, 2, LV_GRID_ALIGN_STRETCH, 1, 4);
        lv_obj_set_grid_cell(vol_slider_wrap, LV_GRID_ALIGN_STRETCH, 4, 2, LV_GRID_ALIGN_STRETCH, 1, 4);

        for (size_t i = 0; i < BTN_NUM; ++i)
        {
            int32_t col_pos = (i % 2) ? 2 : 0;
            int32_t row_pos = (i % 2) ? i : (i + 1);
            lv_obj_set_grid_cell(ctrl_btn_list[i].parent, LV_GRID_ALIGN_STRETCH, col_pos, 2, LV_GRID_ALIGN_STRETCH, row_pos, 2);
        }
    }
    else
    {
        static int32_t column_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
        static int32_t row_dsc[] = {LV_GRID_FR(3), LV_GRID_FR(2), LV_GRID_FR(2), LV_GRID_FR(2), LV_GRID_FR(2), LV_GRID_FR(2), LV_GRID_FR(2), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
        lv_obj_set_grid_dsc_array(ctrl_center, column_dsc, row_dsc);

        lv_obj_set_grid_cell(top_bar_wrap, LV_GRID_ALIGN_STRETCH, 0, 6, LV_GRID_ALIGN_STRETCH, 0, 1);
        lv_obj_set_grid_cell(bl_slider_wrap, LV_GRID_ALIGN_STRETCH, 4, 2, LV_GRID_ALIGN_STRETCH, 1, 4);
        lv_obj_set_grid_cell(vol_slider_wrap, LV_GRID_ALIGN_STRETCH, 2, 2, LV_GRID_ALIGN_STRETCH, 1, 4);

        lv_obj_set_grid_cell(ctrl_btn_list[BTN_THEME].parent, LV_GRID_ALIGN_STRETCH, 0, 2, LV_GRID_ALIGN_STRETCH, 1, 2);
        lv_obj_set_grid_cell(ctrl_btn_list[BTN_TRANSLATION].parent, LV_GRID_ALIGN_STRETCH, 0, 2, LV_GRID_ALIGN_STRETCH, 3, 2);
        lv_obj_set_grid_cell(ctrl_btn_list[BTN_ROTATE].parent, LV_GRID_ALIGN_STRETCH, 0, 2, LV_GRID_ALIGN_STRETCH, 5, 2);
        lv_obj_set_grid_cell(ctrl_btn_list[BTN_TWO].parent, LV_GRID_ALIGN_STRETCH, 2, 2, LV_GRID_ALIGN_STRETCH, 5, 2);
    }
}

static void top_bar_init()
{
    lv_obj_update_layout(top_bar_wrap);
    uint32_t font_height = lv_obj_get_height(top_bar_wrap) * 0.5;
    top_bar_title_font = hmi_ttf_create_static("def_font", font_height, 0);

    lv_obj_t *title = lv_label_create(top_bar_wrap);
    lv_label_set_text(title, lv_tr("控制中心"));
    lv_obj_align(title, LV_ALIGN_LEFT_MID, 10, 0);
    lv_obj_set_style_text_font(title, top_bar_title_font, 0);

    setting_icon = lv_image_create(top_bar_wrap);
    lv_image_set_src(setting_icon, hmi_png("gearshape"));
    lv_obj_align(setting_icon, LV_ALIGN_RIGHT_MID, -10, 0);
    lv_image_set_scale(setting_icon, 256 * HMI_PNG_ZOOM_RATE);
    lv_obj_add_flag(setting_icon, LV_OBJ_FLAG_CLICKABLE);
    lv_obj_add_event_cb(setting_icon, setting_icon_clicked_cb, LV_EVENT_CLICKED, NULL);
}

static void top_bar_deinit()
{
    hmi_ttf_del(top_bar_title_font);
    top_bar_title_font = NULL;
}

static void ctrl_btn_init()
{
    ctrl_btn_list[BTN_THEME].subject = &hmi_theme_subj;
    ctrl_btn_list[BTN_TRANSLATION].subject = &hmi_translations_subj;
    ctrl_btn_list[BTN_ROTATE].subject = &hmi_rotate_subj;

    for (size_t i = 0; i < BTN_NUM; ++i)
    {
        ctrl_btn_list[i].obj = lv_button_create(ctrl_btn_list[i].parent);
        lv_obj_t *obj = ctrl_btn_list[i].obj;
        lv_obj_center(obj);
        lv_obj_add_style(obj, &btn_styl, 0);
        lv_obj_add_style(obj, &btn_checked_styl, LV_STATE_CHECKED);
        lv_obj_add_flag(obj, LV_OBJ_FLAG_CHECKABLE);

        ctrl_btn_list[i].icon = lv_image_create(obj);
        lv_obj_t *icon = ctrl_btn_list[i].icon;
        lv_obj_center(icon);
        lv_image_set_scale(icon, 256 * HMI_PNG_ZOOM_RATE);

        if (ctrl_btn_list[i].subject)
            lv_obj_bind_checked(ctrl_btn_list[i].obj, ctrl_btn_list[i].subject);
    }

    lv_obj_remove_style(ctrl_btn_list[BTN_THEME].obj, &btn_checked_styl, LV_STATE_CHECKED);

    lv_obj_add_event_cb(ctrl_btn_list[BTN_TRANSLATION].obj, translation_btn_clicked_cb, LV_EVENT_CLICKED, NULL);
}

static void slider_init()
{
    lv_obj_t *bl_slider = lv_slider_create(bl_slider_wrap);
    lv_obj_center(bl_slider);
    lv_obj_add_style(bl_slider, &slider_styl, 0);
    lv_obj_add_style(bl_slider, &slider_knob_styl, LV_PART_KNOB);
    lv_obj_add_style(bl_slider, &slider_indicator_style, LV_PART_INDICATOR);

    lv_obj_t *bl_slider_icon = lv_image_create(bl_slider);
    lv_image_set_src(bl_slider_icon, hmi_png("sun_max"));
    lv_obj_align(bl_slider_icon, LV_ALIGN_BOTTOM_MID, 0, -15);
    lv_image_set_scale(bl_slider_icon, 256 * HMI_PNG_ZOOM_RATE);

    lv_obj_t *vol_slider = lv_slider_create(vol_slider_wrap);
    lv_obj_center(vol_slider);
    lv_obj_add_style(vol_slider, &slider_styl, 0);
    lv_obj_add_style(vol_slider, &slider_knob_styl, LV_PART_KNOB);
    lv_obj_add_style(vol_slider, &slider_indicator_style, LV_PART_INDICATOR);

    lv_obj_t *vol_slider_icon = lv_image_create(vol_slider);
    lv_image_set_src(vol_slider_icon, hmi_png("speaker_wave_3"));
    lv_obj_align(vol_slider_icon, LV_ALIGN_BOTTOM_MID, 0, -15);
    lv_image_set_scale(vol_slider_icon, 256 * HMI_PNG_ZOOM_RATE);
}

static void setting_icon_clicked_cb(lv_event_t *e)
{
    LV_UNUSED(e);

    hmi_pg_push(hmi_pg_setting());
}

static void ctrl_center_gesture_cb()
{
    if (ctrl_center_is_down)
        hmi_ctrl_center_up();
}

static void translation_btn_clicked_cb(lv_event_t *e)
{
    LV_UNUSED(e);

    hmi_rebuil_all_pg();
}
